/*
 * TraceabilityTreeBLL.java
 *
 * $Id: TraceabilityTreeBLL.java,v 1.2 2008-06-26 10:42:17 mario Exp $
 */
package org.ceteca.explica.core.traceability.tree.bl;

import java.math.BigDecimal;
import java.net.URL;
import java.util.ArrayList;

import org.ceteca.javaglade.InterfaceGladeParser;
import org.ceteca.explica.core.traceability.InterfaceTraceabilityErrors;
import org.ceteca.explica.core.traceability.InterfaceTraceabilityTree;
import org.ceteca.explica.client.ClientContext;
import org.ceteca.explica.client.traceability.gui.TraceabilityTreeItem;
import org.ceteca.explica.core.traceability.tree.ProcessInfo;
import org.ceteca.explica.core.traceability.tree.ProductInfo;
import org.ceteca.explica.core.traceability.tree.PropertyInfo;
import org.ceteca.explica.core.traceability.tree.PurchaseInfo;
import org.ceteca.explica.core.traceability.tree.WarehouseInfo;
import org.ceteca.explica.core.traceability.tree.WorkcenterInfo;
import org.ceteca.explica.core.traceability.tree.WorkerInfo;
import org.ceteca.explica.core.util.DateTime;
import org.ceteca.explica.core.util.Validator;
import org.ceteca.explica.core.util.LoggerFactory;
import org.ceteca.explica.core.util.ResultMessage;
import org.ceteca.explica.core.util.ResultMessageCatalog;
import org.xnap.commons.i18n.I18n;
import org.xnap.commons.i18n.I18nFactory;

/**
 * Business Logic class that implements the Traceability 
 * Tree Viewer business logic processes. 
 * <br/>
 * Responsibilities:
 * <ul>
 * 	<li>Validation of the traceability tree contents.</li>
 *  <li>Traceability tree creation.</li>
 *  <li>Save traceability tree content to a traceability file.</li>
 *  <li>Remove traceability tree content.</li>
 *  <li>Build a traceability tree from a traceability file.</li>
 * </ul>
 * <br/>
 * @author Mario García García <mario@imagos.es>
 * Copyright (c) 2007 Fundación Centro Tecnolóxico da Carne
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * <br/>
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * <br/>
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
public class TraceabilityTreeBLL {
	/** Unique instance of the TraceabilityTreeBLL class. Singleton pattern */
	private static TraceabilityTreeBLL instance;
	

	/** Returns the unique instance of the TraceabilityTreeBLL class.
	 * Implements the singleton dessign pattern.
	 * @return TraceabilityTreeBLL, unique instance of TraceabilityTreeBLL.
	 */
	public static final TraceabilityTreeBLL getInstance() {
		if (instance == null)
			instance = new TraceabilityTreeBLL();
		return instance;
	}

	/**
	 * Default constructor.
	 */
	private TraceabilityTreeBLL() {
	}
	
	/**
	 * Validates the item, checking that the item data is correct.
	 * It also checks the compatibility amongst the item and its parent 
	 * item.
	 * @param type int, item type.
	 * @param info Object, item data.
	 * @param parentType int, parent item type.
	 * @return ArrayList<ResultMessage>, List of messages with the result of the
	 * validation process. It may be an OK message if the validation
	 * was correct, or a list of detailed error messages ready to be showed
	 * to the user in case the validation was incorrect. 
	 */
	public ArrayList<ResultMessage> validateTreeItem(int type, Object info, int parentType) {
		ArrayList<ResultMessage> result = new ArrayList<ResultMessage>();

		// Check the compatibility between parent type and insert node type.
		// If no parent --> The only valid node type is NODE_PRODUCT
		if (parentType == TraceabilityTreeItem.NODE_UNDEFINED) {
			if (type != TraceabilityTreeItem.NODE_PRODUCT) {
				ArrayList lParams = new ArrayList();
				lParams.add(new Integer(type));
				result.add(ClientContext.getInstance().getMsgCatalog()
						.newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_NO_PARENT, lParams));
			}
		} // if parent == null
		// Else parent is not null
		else {
			switch (parentType) {
				// If the parent node is of type product
				case TraceabilityTreeItem.NODE_PRODUCT:
					// The children nodes of a product node can be of any of
					// these allowed types: PROPERTY, COMMENT, WAREHOUSE, PROCESS, PURCHASE
					if (type != TraceabilityTreeItem.NODE_PROPERTY &&
						type != TraceabilityTreeItem.NODE_COMMENT &&
						type != TraceabilityTreeItem.NODE_WAREHOUSE &&
						type != TraceabilityTreeItem.NODE_PROCESS &&
						type != TraceabilityTreeItem.NODE_PURCHASE) {
						
						ArrayList lParams = new ArrayList();
						lParams.add(new Integer(type));
						result.add(ClientContext.getInstance().getMsgCatalog()
								.newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_NO_PRODUCT_CHILD, lParams));
					}
					break;
				// If the parent node is of type process
				case TraceabilityTreeItem.NODE_PROCESS:
					// The children nodes of a process node can be of any of
					// these allowed types: PRODUCT, WORKER, WORKCENTER, COMMENT
					if (type != TraceabilityTreeItem.NODE_PRODUCT &&
						type != TraceabilityTreeItem.NODE_WORKER &&
						type != TraceabilityTreeItem.NODE_WORKCENTER &&
						type != TraceabilityTreeItem.NODE_COMMENT) {

						ArrayList lParams = new ArrayList();
						lParams.add(new Integer(type));
						result.add(ClientContext.getInstance().getMsgCatalog()
								.newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_NO_PROCESS_CHILD, lParams));
					}
					break;
				// If the parent node is of type warehouse
				case TraceabilityTreeItem.NODE_WAREHOUSE:
					// Only appcc children are allowed
					if (type != TraceabilityTreeItem.NODE_APPCC) {
						ArrayList lParams = new ArrayList();
						lParams.add(new Integer(type));
						result.add(ClientContext.getInstance().getMsgCatalog()
								.newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_NO_WAREHOUSE_CHILD, lParams));
					}
					break;
				// If the parent node is of any other type
				default:
					// Return error of validation, because no other type
					// can have children nodes.
					ArrayList lParams = new ArrayList();
					lParams.add(new Integer(parentType));
					lParams.add(new Integer(type));
					result.add(ClientContext.getInstance().getMsgCatalog()
							.newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_ITEM_NO_CHILD, lParams));
					break;
			} // switch parent node type
		}
		
		// Check the validity of the user typed in data
		// Info typed in cannot be null
		if (info == null) {
			result.add(ClientContext.getInstance().getMsgCatalog()
					.newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_ITEM_NO_DATA));	
		}
		// else if the compatibility validation has been passed on
		else if (result == null || result.size() <= 0) {
			switch (type) {
				// If the inserted node is of type product
				case TraceabilityTreeItem.NODE_PRODUCT:
					result = this.validateProduct((ProductInfo)info);
					break;				
				// if the inserted node is of type purchase
				case TraceabilityTreeItem.NODE_PURCHASE:
					result = this.validatePurchase((PurchaseInfo)info);
					break;
				// If the inserted node is of type property
				case TraceabilityTreeItem.NODE_PROPERTY:
					result = this.validateProperty((PropertyInfo)info);
					break;
				// If the inserted node is of type warehouse
				case TraceabilityTreeItem.NODE_WAREHOUSE:
					result = this.validateWarehouse((WarehouseInfo)info);					
					break;
				// If the inserted node is of type comment
				case TraceabilityTreeItem.NODE_COMMENT:
					result = this.validateComment((String)info);
					break;
				// If the inserted node is of type process
				case TraceabilityTreeItem.NODE_PROCESS:
					result = this.validateProcess((ProcessInfo)info);
					break;				
				// If the inserted node is of type worker
				case TraceabilityTreeItem.NODE_WORKER:
					result = this.validateWorker((WorkerInfo)info);
					break;
				// If the inserted node is of type workcenter
				case TraceabilityTreeItem.NODE_WORKCENTER:
					result = this.validateWorkcenter((WorkcenterInfo)info);
					break;
				// If the inserted node is of type appcc
				case TraceabilityTreeItem.NODE_APPCC:
					break;
				// If the inserted node is of type undefined
				case TraceabilityTreeItem.NODE_UNDEFINED:
					ArrayList lParams = new ArrayList();
					lParams.add(new Integer(type));
					result.add(ClientContext.getInstance().getMsgCatalog()
							.newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_UNDEFINED, lParams));
					break;
			} // switch inserted node type
		} // else the info typed in is not null
		
		return result;
	}

	/**
	 * Check if the product information typed in by the user is correct.
	 * For a new product user must type in at least:
	 * <ul>
	 * <li>REFERENCE: Numeric</li>
	 * <li>SET NUMBER: Numeric</li>
	 * <li>BARCODE: Numeric (valid barcode)</li>
	 * <li>DESCRIPTION: String</li>
	 * <li>IN_DATE: Date</li>
	 * <li>EXPIRY_DATE: Date</li>
	 * <li>TRACEABILITY_FILE: File path. (Optional)</li>
	 * </ul>
	 * @param info ProductInfo, information of the product
	 * @return ArrayList<ResultMessage>, List of messages with the result of the
	 * validation process. It may be an OK message if the validation
	 * was correct, or a list of detailed error messages ready to be showed
	 * to the user in case the validation was incorrect.
	 */
	private ArrayList<ResultMessage> validateProduct(ProductInfo info) {
		ArrayList<ResultMessage> result = new ArrayList<ResultMessage>();
		
		// Validate product's reference
		if (!Validator.getInstance().isValidNumeric(info.getReference())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getReference());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PRODUCT_REFERENCE, 
					lParams, InterfaceTraceabilityTree.EDIT_PRODUCT_REFERENCE_ITEMNAME));
		}
		// Validate product's set number
		if (!Validator.getInstance().isValidNumeric(info.getSetNumber())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getSetNumber());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PRODUCT_SETNUMBER,
					lParams, InterfaceTraceabilityTree.EDIT_PRODUCT_SETNUMBER_ITEMNAME));
		}
		// Validate product's barcode
		System.out.println("Validando el codigo de barras del producto: " + info.getBarcode());
		if (!Validator.getInstance().isValidBarcode(info.getBarcode())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getBarcode());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PRODUCT_BARCODE,
					lParams, InterfaceTraceabilityTree.EDIT_PRODUCT_BARCODE_ENTRY_ITEMNAME));
		}
		// Validate product's description
		if (Validator.getInstance().isEmpty(info.getDescription())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getDescription());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PRODUCT_DESCRIPTION,
					lParams, InterfaceTraceabilityTree.EDIT_PRODUCT_DESCRIPTION_ITEMNAME));
		}
		boolean errorInDate = false;
		// Validate product's in date
		if (!Validator.getInstance().isValidDate(info.getDateIn())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getDateIn());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PRODUCT_INDATE,
					lParams,
					InterfaceTraceabilityTree.EDIT_PRODUCT_IN_DAY_ITEMNAME + "|" +
					InterfaceTraceabilityTree.EDIT_PRODUCT_IN_MONTH_ITEMNAME + "|" +
					InterfaceTraceabilityTree.EDIT_PRODUCT_IN_YEAR_ITEMNAME));
			errorInDate = true;
		}
		// Validate product's expiry date
		if (!Validator.getInstance().isValidDate(info.getDateExpiry())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getDateExpiry());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PRODUCT_EXPIRYDATE,
					lParams,
					InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_DAY_ITEMNAME + "|" +
					InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_MONTH_ITEMNAME + "|" +
					InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_YEAR_ITEMNAME));
			errorInDate = true;
		}
		// Validate expiry date is after in date
		if (!errorInDate && !Validator.getInstance().isDateAfter(info.getDateExpiry(), info.getDateIn())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getDateIn());
			lParams.add(info.getDateExpiry());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PRODUCT_INDATE_AFTER_EXPIRYDATE, lParams));
		}
		// Validate product's traceability file name
		if (!Validator.getInstance().isEmpty(info.getTraceabilityFile()) && 
			!Validator.getInstance().isValidFile(info.getTraceabilityFile())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getTraceabilityFile());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PRODUCT_TRFILENAME,
					lParams, InterfaceTraceabilityTree.EDIT_PRODUCT_TRFILE_ITEMNAME));
		}

		// If no error has taken place then the validation of the product is OK
		if (result == null || result.size() <= 0) {
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_OK));
		}
		
		return result;
	}
	
	/**
	 * Check if the process information typed in by the user is correct.
	 * For a new process, user must type in at least:
	 * <ul>
	 * <li>PROCESS_CODE: Numeric</li>
	 * <li>PROCESS_DATE: Date</li>
	 * </ul>
	 * @param info ProcessInfo, information of the process.
	 * @return ArrayList<ResultMessage>, List of messages with the result of the
	 * validation process. It may be an OK message if the validation
	 * was correct, or a list of detailed error messages ready to be showed
	 * to the user in case the validation was incorrect.
	 */
	private ArrayList<ResultMessage> validateProcess(ProcessInfo info) {
		ArrayList<ResultMessage> result = new ArrayList<ResultMessage>();
		// Validate process's code
		if (Validator.getInstance().isEmpty(info.getCodOperation())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getCodOperation());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROCESS_CODE,
					lParams, InterfaceTraceabilityTree.EDIT_PROCESS_CODE_ITEMNAME));
		}
		// Validate process's date
		if (!Validator.getInstance().isValidDate(info.getDateProcess())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getDateProcess());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROCESS_DATE,
					lParams, 
					InterfaceTraceabilityTree.EDIT_PROCESS_DAY_ITEMNAME + "|" +
					InterfaceTraceabilityTree.EDIT_PROCESS_MONTH_ITEMNAME + "|" +
					InterfaceTraceabilityTree.EDIT_PROCESS_YEAR_ITEMNAME));
		}

		// If no error has taken place then the validation of the product is OK
		if (result == null || result.size() <= 0) {
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_OK));
		}
		
		return result;
	}

	/**
	 * Check if the purchase information typed in by the user is correct.
	 * For a new purchase, user must type in at least:
	 * <ul>
	 * <li>PURCHASE_CODE: Numeric</li>
	 * <li>SUPPLIER_CODE: Numeric</li>
	 * </ul>
	 * @param info PurchaseInfo, information of the purchase.
	 * @return ArrayList<ResultMessage>, List of messages with the result of the
	 * validation process. It may be an OK message if the validation
	 * was correct, or a list of detailed error messages ready to be showed
	 * to the user in case the validation was incorrect.
	 */
	private ArrayList<ResultMessage> validatePurchase(PurchaseInfo info) {
		ArrayList<ResultMessage> result = new ArrayList<ResultMessage>();
		// Validate purchase's code
		if (!Validator.getInstance().isValidNumeric(info.getCodPurchaseConfirmation())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getCodPurchaseConfirmation());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PURCHASE_CODE,
					lParams, InterfaceTraceabilityTree.EDIT_PURCHASE_CODE_ITEMNAME));
		}
		// Validate purchase's supplier code
		if (!Validator.getInstance().isValidNumeric(info.getCodSupplier())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getCodSupplier());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PURCHASE_SUPPLIER,
					lParams, InterfaceTraceabilityTree.EDIT_PURCHASE_SUPPLIER_ITEMNAME));
		}

		// If no error has taken place then the validation of the product is OK
		if (result == null || result.size() <= 0) {
			result.add(ClientContext.getInstance().getMsgCatalog()
					.newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_OK));
		}

		return result;
	}
	
	/**
	 * Check if the property information typed in by the user is correct.
	 * For a new property, user must type in at least:
	 * <ul>
	 * <li>PROPERTY_CODE: Alpha</li>
	 * <li>PROPERTY_DESCRIPTION: Date</li>
	 * <li>PROPERTY_TYPE: Numeric</li>
	 * <li>PROPERTY_VALUE: Alpha</li>
	 * <li>PROPERTY_PATTERN: Alpha (Optional)</li>
	 * </ul>
	 * @param info PropertyInfo, information of the property.
	 * @return ArrayList<ResultMessage>, List of messages with the result of the
	 * validation process. It may be an OK message if the validation
	 * was correct, or a list of detailed error messages ready to be showed
	 * to the user in case the validation was incorrect.
	 */
	private ArrayList<ResultMessage> validateProperty(PropertyInfo info) {
		ArrayList<ResultMessage> result = new ArrayList<ResultMessage>();
		// Validate property's code
		if (!Validator.getInstance().isValidAlpha(info.getCod())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getCod());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROPERTY_CODE,
					lParams, InterfaceTraceabilityTree.EDIT_PROPERTY_CODE_ITEMNAME));
		}
		// Validate property's description
		if (Validator.getInstance().isEmpty(info.getDescription())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getDescription());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROPERTY_DESCRIPTION,
					lParams, InterfaceTraceabilityTree.EDIT_PROPERTY_DESCRIPTION_ITEMNAME));
		}
		// Validate property's type
		String type = (String)PropertyInfo.propertyTypes.get(info.getType());
		if (type == null || type.length() <= 0) {
			ArrayList lParams = new ArrayList();
			lParams.add(type);
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROPERTY_TYPE,
					lParams, InterfaceTraceabilityTree.EDIT_PROPERTY_TYPE_ITEMNAME));
		}
		
		// Temporary store of the value in string format
		String strValue = null;
		
		boolean errorInValue = false;
		// Validate property's value
		if (info.getVal() == null) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getVal());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROPERTY_VALUE,
					lParams, InterfaceTraceabilityTree.EDIT_PROPERTY_VALUE_ITEMNAME));
			errorInValue = true;
		}
		// Validate property's value against type
		else {
			switch (info.getType()) {
				case PropertyInfo.PROPERTY_TYPE_NUMBER:
					if (!(info.getVal() instanceof BigDecimal)) {
						ArrayList lParams = new ArrayList();
						lParams.add(info.getType());
						lParams.add(info.getVal());
						result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROPERTY_VALUE_NOT_MATCH_TYPE,
								lParams, InterfaceTraceabilityTree.EDIT_PROPERTY_VALUE_ITEMNAME));
						errorInValue = true;
						strValue = ((BigDecimal)info.getVal()).toPlainString();
					}
					break;
				case PropertyInfo.PROPERTY_TYPE_BOOLEAN:
					if (!(info.getVal() instanceof Boolean)) {
						ArrayList lParams = new ArrayList();
						lParams.add(info.getType());
						lParams.add(info.getVal());
						result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROPERTY_VALUE_NOT_MATCH_TYPE,
								lParams, InterfaceTraceabilityTree.EDIT_PROPERTY_VALUE_ITEMNAME));
						errorInValue = true;
						strValue = null;
					}
					break;
				case PropertyInfo.PROPERTY_TYPE_DATE:
					if (!(info.getVal() instanceof DateTime)) {
						ArrayList lParams = new ArrayList();
						lParams.add(info.getType());
						lParams.add(info.getVal());
						result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROPERTY_VALUE_NOT_MATCH_TYPE,
								lParams, InterfaceTraceabilityTree.EDIT_PROPERTY_VALUE_ITEMNAME));
						errorInValue = true;
						strValue = ((DateTime)info.getVal()).getDateAsString();
					}
					break;
				case PropertyInfo.PROPERTY_TYPE_STRING:
					if (!(info.getVal() instanceof String)) {
						ArrayList lParams = new ArrayList();
						lParams.add(info.getType());
						lParams.add(info.getVal());
						result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROPERTY_VALUE_NOT_MATCH_TYPE,
								lParams, InterfaceTraceabilityTree.EDIT_PROPERTY_VALUE_ITEMNAME));
						errorInValue = true;
						strValue = (String)info.getVal();
					}
					break;
				case PropertyInfo.PROPERTY_TYPE_OBJECT:
					strValue = null;
					break;
			} // switch property type
		} // else value != null
		
		// Validate property's value against pattern
		if (!errorInValue && info.getPattern() != null && strValue != null) {
			if (!strValue.matches(info.getPattern())) {
				ArrayList lParams = new ArrayList();
				lParams.add(info.getType());
				lParams.add(info.getPattern());
				lParams.add(info.getVal());
				result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_PROPERTY_VALUE_NOT_MATCH_PATTERN,
						lParams, InterfaceTraceabilityTree.EDIT_PROPERTY_VALUE_ITEMNAME));
			}
		} // if property has pattern
	
		
		// If no error has taken place then the validation of the product is OK
		if (result == null || result.size() <= 0) {
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_OK));
		}

		return result;
	}
	
	/**
	 * Check if the warehouse information typed in by the user is correct.
	 * For a new warehouse, user must type in at least:
	 * <ul>
	 * <li>WAREHOUSE_CODE: Numeric</li>
	 * <li>WAREHOUSE_DESCRIPTION: Alpha</li>
	 * </ul>
	 * @param info WarehouseInfo, information of the warehouse.
	 * @return ArrayList<ResultMessage>, List of messages with the result of the
	 * validation process. It may be an OK message if the validation
	 * was correct, or a list of detailed error messages ready to be showed
	 * to the user in case the validation was incorrect.
	 */
	private ArrayList<ResultMessage> validateWarehouse(WarehouseInfo info) {
		ArrayList<ResultMessage> result = new ArrayList<ResultMessage>();
		// Validate warehouse's code
		if (!Validator.getInstance().isValidNumeric(info.getCodWarehouse())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getCodWarehouse());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_WAREHOUSE_CODE,
					lParams, InterfaceTraceabilityTree.EDIT_WAREHOUSE_CODE_ITEMNAME));
		}
		// Validate warehouse's description
		if (Validator.getInstance().isEmpty(info.getDescription())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getDescription());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_WAREHOUSE_DESCRIPTION,
					lParams, InterfaceTraceabilityTree.EDIT_WAREHOUSE_DESCRIPTION_ITEMNAME));
		}

		// If no error has taken place then the validation of the product is OK
		if (result == null || result.size() <= 0) {
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_OK));
		}
		
		return result;
	}

	/**
	 * Check if the worker information typed in by the user is correct.
	 * For a new worker, user must type in at least:
	 * <ul>
	 * <li>WORKER_CODE: Numeric</li>
	 * <li>WORKER_NAME: Alpha</li>
	 * </ul>
	 * @param info WorkerInfo, information of the worker.
	 * @return ArrayList<ResultMessage>, List of messages with the result of the
	 * validation process. It may be an OK message if the validation
	 * was correct, or a list of detailed error messages ready to be showed
	 * to the user in case the validation was incorrect.
	 */
	private ArrayList<ResultMessage> validateWorker(WorkerInfo info) {
		ArrayList<ResultMessage> result = new ArrayList<ResultMessage>();
		// Validate warehouse's code
		if (!Validator.getInstance().isValidNumeric(info.getCodWorker())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getCodWorker());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_WORKER_CODE,
					lParams, InterfaceTraceabilityTree.EDIT_WORKER_CODE_ITEMNAME));
		}
		// Validate warehouse's description
		if (Validator.getInstance().isEmpty(info.getDescription())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getDescription());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_WORKER_DESCRIPTION,
					lParams, InterfaceTraceabilityTree.EDIT_WORKER_NAME_ITEMNAME));
		}

		// If no error has taken place then the validation of the product is OK
		if (result == null || result.size() <= 0) {
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_OK));
		}
		
		return result;
	}
	
	/**
	 * Check if the workcenter information typed in by the user is correct.
	 * For a new workcenter, user must type in at least:
	 * <ul>
	 * <li>WORKCENTER_CODE: Numeric</li>
	 * <li>WORKCENTER_DESCRIPTION: Alpha</li>
	 * </ul>
	 * @param info WorkcenterInfo, information of the workcenter.
	 * @return ArrayList<ResultMessage>, List of messages with the result of the
	 * validation process. It may be an OK message if the validation
	 * was correct, or a list of detailed error messages ready to be showed
	 * to the user in case the validation was incorrect.
	 */
	private ArrayList<ResultMessage> validateWorkcenter(WorkcenterInfo info) {
		ArrayList<ResultMessage> result = new ArrayList<ResultMessage>();
		// Validate warehouse's code
		if (!Validator.getInstance().isValidNumeric(info.getCodWorkcenter())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getCodWorkcenter());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_WORKCENTER_CODE,
					lParams, InterfaceTraceabilityTree.EDIT_WORKCENTER_CODE_ITEMNAME));
		}
		// Validate warehouse's description
		if (Validator.getInstance().isEmpty(info.getDescription())) {
			ArrayList lParams = new ArrayList();
			lParams.add(info.getDescription());
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_WORKCENTER_DESCRIPTION,
					lParams, InterfaceTraceabilityTree.EDIT_WORKCENTER_DESCRIPTION_ITEMNAME));
		}

		// If no error has taken place then the validation of the product is OK
		if (result == null || result.size() <= 0) {
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_OK));
		}
		
		return result;
	}
	
	/**
	 * Check if the comment information typed in by the user is correct.
	 * For a new comment, user must type in at least:
	 * <ul>
	 * <li>COMMENT: Alpha (Not null)</li>
	 * </ul>
	 * @param info String, information of the comment.
	 * @return ArrayList<ResultMessage>, List of messages with the result of the
	 * validation process. It may be an OK message if the validation
	 * was correct, or a list of detailed error messages ready to be showed
	 * to the user in case the validation was incorrect.
	 */
	private ArrayList<ResultMessage> validateComment(String info) {
		ArrayList<ResultMessage> result = new ArrayList<ResultMessage>();
		// Validate warehouse's code
		if (Validator.getInstance().isEmpty(info)) {
			ArrayList lParams = new ArrayList();
			lParams.add(info);
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_COMMENT,
					lParams, InterfaceTraceabilityTree.EDIT_COMMENT_ITEMNAME));
		}

		// If no error has taken place then the validation of the product is OK
		if (result == null || result.size() <= 0) {
			result.add(ClientContext.getInstance().getMsgCatalog().newResultMessage(InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_OK));
		}
		
		return result;	
	}
	
	/**
	 * This method analyses the list of result messages got from a tree item
	 * validation process, to determine if the item is valid or not.
	 * @param lResult ArrayList<ResultMessage>, List of messages got from
	 * the tree item validation process.
	 * @return boolean, True if the item is valid; False in any other case.
	 * @see org.ceteca.explica.traceability.bl.TraceabilityTreeBLL#validateTreeItem
	 */
	public boolean isTreeItemCorrect(ArrayList<ResultMessage> lResult) {
		boolean result = false;

		// Item is valid only if there is a result message with the 
		// ITEM_VALIDATION_OK message code.
		if (lResult != null && lResult.size() == 1) {
			ResultMessage mes = lResult.get(0);
			result = mes != null && mes.getResCode() == InterfaceTraceabilityErrors.ERR_TRACEABILITY_ITEM_VALIDATION_OK;
		}
			
		return result;
	}
	
	/**
	 * Returns tag Id assigned to CVS source file.
	 */
	public static String getRevision() {
		return "$Id: TraceabilityTreeBLL.java,v 1.2 2008-06-26 10:42:17 mario Exp $";
	}
}
